package com.jvm.interpreter.instruction;

import com.jvm.Utils;
import com.jvm.classfile.model.Class;
import com.jvm.classfile.model.CpInfo;
import com.jvm.classfile.model.Method;
import com.jvm.interpreter.ExecEnv;
import com.jvm.interpreter.Frame;
import com.jvm.interpreter.Instruction;
import com.jvm.interpreter.MetaSpace;

import java.io.DataInputStream;
import java.io.IOException;

/**
 * @program: diy_simple_jvm
 * @description: invokestatic指令
 * @author: CaoYong
 * @create: 2021-07-09 14:15
 **/
public class InvokeStaticInst implements Instruction {

    final String clazz;
    final String name;
    final String descriptor;

    public InvokeStaticInst(String clazz, String name, String descriptor) {
        this.clazz = clazz;
        this.name = name;
        this.descriptor = descriptor;
    }

    @Override
    public int offset() {
        return 3;
    }

    @Override
    public void eval(Frame frame) {
        Class clazz = MetaSpace.getClassLoader().findClass(this.clazz);
        Method method = clazz.getStaticMethod(name, descriptor);
        Utils.clinit(method.clazz);

        Utils.invokeMethod(method);

//        Frame newFrame = new Frame(method);
//        final ExecEnv env = MetaSpace.getMainEnv();
//        final Frame old = env.topFrame();
//
//        final int slots = method.getArgSlotSize();
//        for (int i = slots - 1; i >= 0 ; i--) {
//            newFrame.set(i, old.pop());
//        }
//        env.pushFrame(frame);

        frame.pc += offset();
    }

    static InvokeStaticInst parse(DataInputStream dis, CpInfo[] cp) throws IOException {
        int isi = dis.readUnsignedShort();
        return new InvokeStaticInst(Utils.getClassNameFromMethodRef(cp, isi), Utils.getNameFromMethodRef(cp, isi), Utils.getDescriptorFromMethodRef(cp, isi));
    }
}
